import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author yitta
 * @date 2023/6/19 16:31
 */

@WebServlet("/Student")
public class servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Query-doGet...");
        doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 读取学生数据
        ArrayList<Student> students = readStudents("C:\\Users\\huawei\\Desktop\\Student\\student.txt");
        request.setCharacterEncoding("utf-8");
        // 实现搜索功能
        String name = request.getParameter("name");
        System.out.println(name);
        ArrayList<Student> searchResult = searchStudents(students, name);
        System.out.println("Search result:");
        for(Student s : searchResult) {
            System.out.println(s);
        }
        // 实现相似学生推荐功能
        ArrayList<Student> recommendResult = recommendSimilarStudents(students, name, 3);

        Gson gson = new Gson();
        String json = gson.toJson(recommendResult);

        // 保存json文件到指定路径
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(json);
    }



    // 读取学生数据
    public static ArrayList<Student> readStudents(String filename) {
        ArrayList<Student> students = new ArrayList<Student>();
        try {
            BufferedReader br = new BufferedReader(new FileReader(filename));
            String line;
            while ((line = br.readLine()) != null) {
                String[] fields = line.split(",");
                String name = fields[0];
                double gpa = Double.parseDouble(fields[1]);
                String subject = fields[2];
                Student s = new Student(name, gpa, subject);
                students.add(s);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return students;
    }

    // 实现搜索功能
    public static ArrayList<Student> searchStudents(ArrayList<Student> students, String name) {
        ArrayList<Student> result = new ArrayList<Student>();
        for(Student s : students) {
            if(s.getName().equals(name)) {
                result.add(s);
            }
        }
        return result;
    }

    // 实现相似学生推荐功能
    public static ArrayList<Student> recommendSimilarStudents(ArrayList<Student> students, String targetName, int num) {
        ArrayList<Student> result = new ArrayList<Student>();
        // 找到目标学生的绩点
        double targetGpa = 0;
        for(Student s : students) {
            if(s.getName().equals(targetName)) {
                targetGpa = s.getGpa();
                break;
            }
        }
        // 计算与目标学生最相似的学生
        HashMap<String, Double> similarities = new HashMap<String, Double>();
        for(Student s : students) {
            double similarity = cosineSimilarity(targetGpa, s.getGpa());
            similarities.put(s.getName(), similarity);
        }
        for(int i = 0; i < num; i++) {
            String maxName = "";
            double maxSimilarity = 0;
            for(String name : similarities.keySet()) {
                if(similarities.get(name) > maxSimilarity && !name.equals(targetName)) {
                    maxName = name;
                    maxSimilarity = similarities.get(name);
                }
            }
            result.add(searchStudents(students, maxName).get(0));
            similarities.remove(maxName);
        }
        System.out.println(result);
        return result;
    }

    // 计算余弦相似度
    public static double cosineSimilarity(double x, double y) {
        double dotProduct = x * y;
        double xMagnitude = Math.sqrt(x * x);
        double yMagnitude = Math.sqrt(y * y);
        return dotProduct / (xMagnitude * yMagnitude);
    }

}
